package com.vframework.config.shiro;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;

/***************************************************************
 * Name:        ShiroConfiguration.java
 * Create At:   2018年4月17日
 * Module:      
 * Description: [shiro配置项]
 * @author      shanzhitong
 * ------------------------------------------------------------
 * 修改历史
 * 序号         日期                       修改人               修改原因
 * 1    2018年4月17日      shanzhitong    
 * 2
***************************************************************/
@Configuration
//标注启动了缓存
//@EnableCaching
@Import(ShiroManager.class)
public class ShiroConfiguration {

    @Bean(name = "realm")
    @DependsOn("lifecycleBeanPostProcessor")
    @ConditionalOnMissingBean
    public Realm realm() {
        return new ShiroRealm();
    }
    
    /**
     * 用户授权信息Cache
     */
    @Bean(name = "shiroCacheManager")
    @ConditionalOnMissingBean
    public CacheManager cacheManager() {
        return new MemoryConstrainedCacheManager();
    }
    
    @Bean(name = "securityManager")
    @ConditionalOnMissingBean
    public DefaultSecurityManager securityManager() {
        DefaultSecurityManager sm = new DefaultWebSecurityManager();
//        sm.setCacheManager(cacheManager());
        return sm;
    }
    
    /**
     * ShiroFilterFactoryBean 处理拦截资源文件问题。
     * 注意：单独一个ShiroFilterFactoryBean配置是或报错的，以为在
     * 初始化ShiroFilterFactoryBean的时候需要注入：SecurityManager
     *
     * Filter Chain定义说明 
     * 1、一个URL可以配置多个Filter，使用逗号分隔 
     * 2、当设置多个过滤器时，全部验证通过，才视为通过
     * 3、部分过滤器可指定参数，如perms，roles
     */
    @Bean(name = "shiroFilter")
    @DependsOn("securityManager")
    @ConditionalOnMissingBean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager securityManager, Realm realm){
        securityManager.setRealm(realm);
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        shiroFilter.setSecurityManager(securityManager);
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilter.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        shiroFilter.setSuccessUrl("/index");
        // 未授权界面;
        shiroFilter.setUnauthorizedUrl("/403");
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 拦截器.
        Map<String, String> filterChainDefinitionManager = new LinkedHashMap<String, String>();
        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionManager.put("/statics/**", "anon");//anon 可以理解为不拦截
        filterChainDefinitionManager.put("/images/**", "anon");//anon 可以理解为不拦截
        filterChainDefinitionManager.put("/plugins/**", "anon");//anon 可以理解为不拦截
        filterChainDefinitionManager.put("/scripts/**", "anon");//anon 可以理解为不拦截
        filterChainDefinitionManager.put("/styles/**", "anon");//anon 可以理解为不拦截
        // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionManager.put("/logout", "logout");
        // 登录
        filterChainDefinitionManager.put("/SecurityController/**", "anon");
        filterChainDefinitionManager.put("/ImageGenerator/getCode.do", "anon");
        filterChainDefinitionManager.put("/index", "anon");
        filterChainDefinitionManager.put("/", "anon");
        
        
//        filterChainDefinitionManager.put("/user/**", "authc,roles[user]");
//        filterChainDefinitionManager.put("/shop/**", "authc,roles[shop]");
//        filterChainDefinitionManager.put("/admin/**", "authc,roles[admin]");
        filterChainDefinitionManager.put("/ajaxLogin", "anon");
        // 过滤链定义，从上向下顺序执行，一般将 /**放在最为下边 :这是一个坑呢，一不小心代码就不好使了;
        // authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
//        filterChainDefinitionManager.put("/**",  "authc");//其他资源全部拦截
        filterChainDefinitionManager.put("/**",  "anon");
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionManager);
        System.out.println("Shiro拦截器工厂类注入成功");
//        shiroFilter.setLoginUrl("/login");
//        shiroFilter.setSuccessUrl("/");
//        shiroFilter.setUnauthorizedUrl("/403");
        return shiroFilter;
    }
}